package com.mk.seckill.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mk.seckill.exception.GlobalException;
import com.mk.seckill.mapper.UserMapper;
import com.mk.seckill.pojo.User;
import com.mk.seckill.service.IUserService;
import com.mk.seckill.utils.CookieUtil;
import com.mk.seckill.utils.MD5Util;
import com.mk.seckill.utils.UUIDUtil;
import com.mk.seckill.utils.ValidatorUtil;
import com.mk.seckill.vo.LoginVo;
import com.mk.seckill.vo.RespBean;
import com.mk.seckill.vo.RespBeanEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
//
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private RedisTemplate redisTemplate;
//
	@Override
	public RespBean doLogin(LoginVo loginVo, HttpServletRequest request, HttpServletResponse response) {
		/**
		 * @Author hhwu
		 * @Description //TODO 登录业务
		 * @Date 20:11 2022/6/6
		 * @Param [loginVo, request, response]
		 * @return com.xxxx.seckill.vo.RespBean
		 **/
		String mobile = loginVo.getMobile();
		String password = loginVo.getPassword();

//		在LoginController中，对LoginVo对象使用了@Value注解，会对mobile参数自动进行校验，其中，IsMobile注解规则是自定义的
		// 未使用@Value校验功能时的手动参数校验
		 //参数校验
//		 if (StringUtils.isEmpty(mobile)||StringUtils.isEmpty(password)){
//		 	return RespBean.error(RespBeanEnum.LOGIN_ERROR);
//		 }
//		 if (!ValidatorUtil.isMobile(mobile)){
//		 	return RespBean.error(RespBeanEnum.MOBILE_ERROR);
//		 }

		//根据手机号从数据库中查询用户
		User user = userMapper.selectById(mobile);
		if (null == user) {
//			return RespBean.error(RespBeanEnum.LOGIN_ERROR);
//			 抛出的异常会自动被com/mk/seckill/exception/GlobalExceptionHandler分类统一处理
			throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
		}
		//判断密码是否正确
		if (!MD5Util.formPassToDBPass(password, user.getSlat()).equals(user.getPassword())) {
//			return RespBean.error(RespBeanEnum.LOGIN_ERROR);
			throw new GlobalException(RespBeanEnum.LOGIN_ERROR);
		}

		// 验证通过
//		// 生成凭证，凭证在访问每个路径时，都会进行验证
		String ticket = UUIDUtil.uuid();
//		//将用户信息存入redis中
		redisTemplate.opsForValue().set("user:" + ticket, user);// 将凭证作为key，user对象作为value，存入服务器调用的redis中，可以方便服务器集群时查询凭证和对应的用户，因为redis是所有服务器共享的，是分布式部署的
//		request.getSession().setAttribute(ticket,user);// 将凭证存入服务器的session中
		CookieUtil.setCookie(request, response, "userTicket", ticket);// 将凭证再给客户端发一份到cookie
		return RespBean.success(ticket);// 登录成功后，自动执行login.html后边的函数
	}
//
	@Override
	public User getUserByCookie(String userTicket, HttpServletRequest request, HttpServletResponse response) {
		/**
		 * @Author hhwu
		 * @Description //TODO 根据传到服务器的cookie中的ticket获取redis中缓存的用户，返回客户端传来的凭证，获取到对应的user信息
		 * @Date 11:50 2022/6/7
		 * @Param [userTicket, request, response]
		 * @return com.xxxx.seckill.pojo.User
		 **/
		if (StringUtils.isEmpty(userTicket)) {
			return null;
		}
		User user = (User) redisTemplate.opsForValue().get("user:" + userTicket);
		if (user != null) {// 重新设置一下cookie
			CookieUtil.setCookie(request, response, "userTicket", userTicket);
		}
		return user;
	}

	@Override
	public RespBean updatePassword(String userTicket, String password, HttpServletRequest request,
	                               HttpServletResponse response) {
		/**
		 * @Author hhwu
		 * @Description //TODO 更新密码，password是新密码。更新密码后，需要将redis中的ticket删除
		 * @Date 21:03 2022/6/8
		 * @Param [userTicket, password, request, response]
		 * @return com.mk.seckill.vo.RespBean
		 **/
		User user = getUserByCookie(userTicket, request, response);
		if (user == null) {// 如果通过cookie没有获取到用户
			throw new GlobalException(RespBeanEnum.MOBILE_NOT_EXIST);
		}
		user.setPassword(MD5Util.inputPassToDBPass(password, user.getSlat()));
		int result = userMapper.updateById(user);
		if (1 == result) {// 如果数据库中成功更新密码
			//删除Redis中的ticket
			redisTemplate.delete("user:" + userTicket);
			return RespBean.success();
		}
		return RespBean.error(RespBeanEnum.PASSWORD_UPDATE_FAIL);
	}
}
